# -*- coding:utf-8 -*-
import time

from PyQt5.QtWidgets import QDesktopWidget, \
    QPushButton, QHBoxLayout, QVBoxLayout, QWidget, QLabel, QCheckBox,QLineEdit
from PyQt5.QtCore import Qt, pyqtSignal,QRegExp
from PyQt5.QtGui import QRegExpValidator

import threading
import pexpect
import os
import signal
import sys
import pyperclip

WAITTIME=0

sys.path.append(os.path.join(sys.path[0], '../../csi_config'))

from csi_config import read_setting

PASSWD = read_setting('password')
PING=read_setting('ping')
class LaunchServiceWindow(QWidget):
    init_signal = pyqtSignal()
    connect_signal = pyqtSignal(bool)
    openserver_signal = pyqtSignal(bool)
    openservernotalive_signal = pyqtSignal()
    wait_signal = pyqtSignal(int)
    timeout_signal = pyqtSignal()


    def init_thread(self):
        filedir = os.path.dirname(__file__)
        dir = os.path.join(filedir, '../../..')
        cmd = 'python3 ' + os.path.join(dir, 'csi_config/init')
        child = pexpect.spawn(cmd)
        while child.isalive():
            pass
        i = WAITTIME
        while i > 0:
            self.wait_signal.emit(i)
            time.sleep(1)
            i -= 1
        self.init_signal.emit()

    def __init__(self):
        super().__init__()
        self.init_ui()
        self.init_data()

    def init_ui(self):

        self.setWindowTitle('启动/停止Wi-Fi CSI服务 -- zz')
        self.setMaximumSize(700,250)
        screen = QDesktopWidget().screenGeometry()
        size = self.geometry()
        self.move((screen.width() - size.width()) / 2,
                  (screen.height() - size.height()) / 2)

        self.connecthint = QLabel('连接服务')
        self.connecthint.setMinimumWidth(160)
        self.connecthint.setToolTip('<p>连接服务是连接到一Wi-Fi的AP'
                                    '，之后启动dhcp的服务。'
                                    '停止时先关闭dhcp服务，然后断开AP。</p>')
        self.btnconnectstart = QPushButton('启动')
        self.btnconnectstart.clicked.connect(self.onbtnconnectstart)
        self.btnconnectstart.setEnabled(False)
        self.btnconnectstop = QPushButton('停止')
        self.btnconnectstop.clicked.connect(self.onbtnconnectstop)
        self.btnconnectstop.setEnabled(False)
        self.openserverhint = QLabel('CSI服务')
        self.openserverhint.setMinimumWidth(160)
        self.openserverhint.setToolTip('<p>CSI服务是启动一服务器并向外发送CSI信息的服务。'
                                       '<br/><font color=red>'
                                       '<b>注意：当客户端断开时，需要重新打开此服务'
                                       '</b></font></p>')
        self.btnopenserverstart = QPushButton('启动')
        self.btnopenserverstart.clicked.connect(self.onbtnopenserverstart)
        self.btnopenserverstart.setEnabled(False)
        self.btnopenserverstop = QPushButton('停止')
        self.btnopenserverstop.clicked.connect(self.onbtnopenserverstop)
        self.btnopenserverstop.setEnabled(False)

        self.chbautoopenservice = QCheckBox('自动重启')
        self.lblconnect = QLabel()
        self.lblopenserver = QLabel()
        self.init_signal.connect(self.init_ok)

        openserver_l = QHBoxLayout()
        openserver_l.addWidget(self.openserverhint)
        openserver_l.addWidget(self.btnopenserverstart)
        openserver_l.addWidget(self.btnopenserverstop)
        openserver_l.addWidget(self.chbautoopenservice)
        openserver_l.addWidget(self.lblopenserver)

        connect_l = QHBoxLayout()
        connect_l.addWidget(self.connecthint)
        connect_l.addWidget(self.btnconnectstart)
        connect_l.addWidget(self.btnconnectstop)
        connect_l.addWidget(self.lblconnect)

        connect_l.setStretchFactor(self.connecthint, 1)
        connect_l.setStretchFactor(self.btnconnectstart, 1)
        connect_l.setStretchFactor(self.btnconnectstop, 1)
        connect_l.setStretchFactor(self.lblconnect, 2)
        self.lblconnect.setAlignment(Qt.AlignCenter)
        dir = os.path.join(os.path.dirname(__file__), '../../..')
        self.initlbl = QLabel('<font color=red size=6>正在初始化网卡驱动</font>')
        self.initlbl.setAlignment(Qt.AlignCenter)
        self.conflbl = QLabel('读取配置文件%s' %
                              os.path.join(os.path.abspath(dir),
                                           'csi_config/config.conf'))
        self.conflbl.setAlignment(Qt.AlignCenter)


        ping_l=QHBoxLayout()
        pinghint=QLabel("Ping间隔时间")
        self.lepingitv=QLineEdit()
        self.btnpingcopy=QPushButton('复制')
        ping_l.addWidget(pinghint)
        ping_l.addWidget(self.lepingitv)
        ping_l.addWidget(self.btnpingcopy)

        ping_l.setStretchFactor(pinghint,2)
        ping_l.setStretchFactor(self.lepingitv, 2)
        ping_l.setStretchFactor(self.btnpingcopy, 1)

        self.lepingitv.setMaximumWidth(100)
        self.lepingitv.setText(PING)
        self.btnpingcopy.setEnabled(False)
        self.lepingitv.setValidator(QRegExpValidator(QRegExp(r'[0-9]*\.[0-9]+')))


        v_l = QVBoxLayout()
        v_l.addWidget(self.initlbl)
        v_l.addWidget(self.conflbl)
        v_l.addLayout(connect_l)
       # v_l.addLayout(openserver_l)
        v_l.addLayout(ping_l)

        self.setLayout(v_l)


    def init_data(self):
        self.autoopenservice=False
        self.init_t = threading.Thread(target=self.init_thread)
        self.init_t.start()
        self.connect_signal.connect(self.connect_on)
        self.openserver_signal.connect(self.openserver_on)
        self.openservernotalive_signal.connect(self.openservernotalive)
        self.wait_signal.connect(self.wait_)
        self.timeout_signal.connect(self.timeout_)
        self.chbautoopenservice.stateChanged.connect(self.onchbautoopenservice)
        self.btnpingcopy.clicked.connect(self.onbtnpingcopy)

    def onbtnpingcopy(self):
        pyperclip.copy('echo %s|sudo -S ping -i%s %s' % (PASSWD,self.lepingitv.text(),self.connectdevip))

    def onchbautoopenservice(self,b):
        if b:
            self.autoopenservice=True
        else:
            self.autoopenservice=False

    def wait_(self, t):
        self.initlbl.setText('<font color=red size=6>请稍候，还剩%ds</font>' % t)

    def timeout_(self):
        s = self.connecthint.text()
        idx = s.find('<')
        if idx > 0:
            self.connecthint.setText(s[0:idx])
        self.lblconnect.setText('<font color=red>连接超时</font>')
        self.btnconnectstart.setEnabled(True)

    def openservernotalive(self):
        s = self.openserverhint.text()
        idx = s.find('<')
        if idx > 0:
            self.openserverhint.setText(s[0:idx])
        self.lblopenserver.setText('<font color=red>已结束服务</font>')
        self.btnopenserverstop.setEnabled(False)
        self.btnopenserverstart.setEnabled(True)

        if self.autoopenservice:
            self.onbtnopenserverstart()

    def init_ok(self):
        self.initlbl.setText("<font color=green size=6>初始化网卡驱动成功</font>")
        self.btnconnectstart.setEnabled(True)
        self.btnopenserverstart.setEnabled(True)

    def closeEvent(self, event):
        self.hide()
        connectstop_thread = threading.Thread(target=self.connectstop_t)
        connectstop_thread.start()
        openserverstop_thread = threading.Thread(target=self.openserverstop_t)
        openserverstop_thread.start()
        self.init_t.join()
        connectstop_thread.join()
        openserverstop_thread.join()

    def onbtnconnectstart(self):
        self.btnconnectstart.setEnabled(False)
        self.lblconnect.setText('正在启动')

        connect_thread = threading.Thread(target=self.connect_t)
        connect_thread.start()

    def onbtnconnectstop(self):
        self.btnconnectstop.setEnabled(False)
        self.lblconnect.setText('正在停止')

        connectstop_thread = threading.Thread(target=self.connectstop_t)
        connectstop_thread.start()

    def connect_on(self, b):
        if b:
            self.connecthint.setText(self.connecthint.text()
                                     + '<%d>' % self.connectpid)
            self.lblconnect.setText('SSID：%s<br/>热点IP:<font color=blue>%s</font><br/>本机IP:<font color=orange>%s</font>'
                                    % (self.connectdevname, self.connectdevip,self.serverdevip))
            self.btnconnectstop.setEnabled(True)
            self.btnpingcopy.setEnabled(True)



        else:
            s = self.connecthint.text()
            idx = s.find('<')
            if idx > 0:
                self.connecthint.setText(s[0:idx])
            self.lblconnect.setText('')
            self.btnconnectstart.setEnabled(True)
            self.btnpingcopy.setEnabled(False)

    def openserver_on(self, b):
        if b:
            self.openserverhint.setText(self.openserverhint.text()
                                        + '<%d>' % self.openserverpid)
            self.lblopenserver.setText('端口号:<font color=red>%d</font>' % PORT)
            self.btnopenserverstop.setEnabled(True)
        else:
            s = self.openserverhint.text()
            idx = s.find('<')
            if idx > 0:
                self.openserverhint.setText(s[0:idx])
            self.lblopenserver.setText('')
            self.btnopenserverstart.setEnabled(True)
            if self.autoopenservice:
                self.onbtnopenserverstart()


    def connect_t(self):
        filedir = os.path.dirname(__file__)
        dir = os.path.join(filedir, '../../..')
        cmd = 'python3 ' + os.path.join(dir, 'csi_config/connect -c')
        self.connect_child = pexpect.spawn(cmd)
        self.connectpid = self.connect_child.pid
        try:
            index = self.connect_child.expect(r'\[.*\]')
            if index == 0:
                self.connectdevname = self.connect_child.after[1:-1].decode('utf8')
            index = self.connect_child.expect(r'\d+\.\d+\.\d+\.\d+->\d+\.\d+\.\d+\.\d+')
            if index == 0:
                temp= self.connect_child.after.decode('utf8').split('->')
                self.connectdevip=temp[0]
                self.serverdevip=temp[1]



        except pexpect.TIMEOUT:
            self.timeout_signal.emit()
            return
        except pexpect.EOF:
            raise RuntimeError

        self.connect_signal.emit(True)

    def connectstop_t(self):
        if hasattr(self, 'connectpid'):
            os.kill(self.connectpid, signal.SIGKILL)
            del self.connectpid
        filedir = os.path.dirname(__file__)
        dir = os.path.join(filedir, '../../..')
        cmd = 'python3 ' + os.path.join(dir, 'csi_config/disconnect')
        child = pexpect.spawn(cmd)
        while child.isalive():
            pass
        self.connect_signal.emit(False)

    def openserverstop_t(self):
        if hasattr(self, 'openserverpid'):
            try:
                os.kill(self.openserverpid, signal.SIGKILL)
            except:
                pass
            del self.openserverpid
        if hasattr(self, 'openservermetapid'):
            child = pexpect.spawn('sudo kill %d' % self.openservermetapid)
            index = child.expect('password')
            if index == 0:
                child.sendline(PASSWD)
            while child.isalive():
                pass
            if hasattr(self,'openservermetapid'):
                del self.openservermetapid
        self.openserver_signal.emit(False)

    def onbtnopenserverstart(self):
        self.btnopenserverstart.setEnabled(False)
        self.lblopenserver.setText('正在启动')

        openserver_thread = threading.Thread(target=self.openserver_t)
        openserver_thread.start()

    def openserver_t(self):
        filedir = os.path.dirname(__file__)
        dir = os.path.join(filedir, '../../..')
        cmd = 'python3 ' + os.path.join(dir, 'csi_config/openserver')
        self.openserver_child = pexpect.spawn(cmd)
        try:
            index = self.openserver_child.expect(r'pid=.*?\n')
            if index == 0:
                s = self.openserver_child.after.decode('utf8')
                s.rstrip()
                self.openservermetapid = int(s.split('=')[1])
            self.openserverpid = self.openserver_child.pid
            self.openserveralive_thread = threading.Thread(target=self.openserveralive_t)
            self.openserveralive_thread.start()
            self.openserver_signal.emit(True)
        except pexpect.EOF:
            self.onbtnopenserverstop()
        except pexpect.TIMEOUT:
            self.onbtnopenserverstop()
        except AttributeError:
            pass

    def openserveralive_t(self):
        while self.openserver_child.isalive():
            pass
        self.openservernotalive_signal.emit()

    def onbtnopenserverstop(self):
        self.btnopenserverstop.setEnabled(False)
        self.lblopenserver.setText('正在停止')

        openserverstop_thread = threading.Thread(target=self.openserverstop_t)
        openserverstop_thread.start()
